package com.gallop.common.lock;

import com.gallop.common.CacheKeyAssembleHandler;
import com.gallop.common.cache.assemble.OrderedJoiningKeyAssembleHandler;

import java.lang.annotation.*;
import java.util.concurrent.TimeUnit;

/**
 * 分布式锁
 * <p>
 * 在需要加锁的方法上使用此注解，定义该方法的Class必须是一个spring-bean。
 * <p>
 * 注意： 同一类内部的方法调用不会触发spring-aop，进而导致加锁注解失效。
 * 可autorwired引用自身并添加注解{@link org.springframework.context.annotation.Lazy}解决此问题
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DistributedLock {

    String primaryKey() default "";

    DistributedConstants.LockPrimaryKeyEnum value() default DistributedConstants.LockPrimaryKeyEnum.DEFAULT;

    TimeUnit expireTimeUnit() default TimeUnit.SECONDS;

    /**
     * 锁占用时长，超时后释放锁。
     * 通过{@link #expireTimeUnit()}设置时间单位，默认秒
     */
    long expireAfter() default 5;

    TimeUnit maxWaitTimeUnit() default TimeUnit.SECONDS;

    /**
     * 锁等待时长，如果已设置{@link  #fastFail()}或等待超时，
     * 会触发{@link DistributedConstants.OnFail} 回调。
     * 通过{@link #maxWaitTimeUnit()}设置时间单位，默认秒
     */
    long maxWait() default 10;

    /**
     * 如果有锁直接失败
     */
    boolean fastFail() default false;

    /**
     * 参数拼接方法。
     */
    Class<? extends CacheKeyAssembleHandler> assembleHandler() default OrderedJoiningKeyAssembleHandler.class;

    /**
     * 是否拼接查询参数
     */
    boolean needParam() default true;

    /**
     * 定义加锁流程中可以抛出（不会被回调捕获）的异常类型。（{@link InterruptedException} 默认会被回调捕获）
     * <p>
     * 上下文默认对异常进行捕获，并交由{@link DistributedConstants.OnError}回调处理。
     * <p>
     * 定义在此的异常将直接抛出不被捕获。
     */
    Class<? extends Exception>[] exceptionThrows() default {};
}
